package com.woniu.handler;

import com.woniu.service.impl.SecurityLoginService;
import com.woniu.util.JWTUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 功能点1:判断用户请求是否带jwt凭证,是:继续执行下面逻辑,否:放行不处理
 * 功能点2:判断用户携带的jwt合法性,合法:继续执行下面逻辑,否:放行不处理
 * 功能点3:用户携带的jwt和redis的jwt做对比
 *          1):根据key判断redis是否有,(key的获取方式:解析jwt中的载荷获得的)
 *          2):再判断两个的jwt值是否一样
 */
@Component
public class JWTFilter extends OncePerRequestFilter {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private SecurityLoginService securityLoginService;

    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

        //功能点1
        String jwt = httpServletRequest.getHeader("jwt");
        if(jwt==null){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        //功能点2
        if(!JWTUtil.decode(jwt)){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        //功能点3
        Map payload = JWTUtil.getPayload(jwt);
        String username = (String) payload.get("username");
        String redisJWT = redisTemplate.opsForValue().get("jwt:" + username);
        if(redisJWT==null){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        if(!jwt.equals(redisJWT)){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        redisTemplate.opsForValue().set("jwt:"+username,jwt,30, TimeUnit.MINUTES);
        //jwt校验成功
        UserDetails userDetails = securityLoginService.loadUserByUsername(username);
        UsernamePasswordAuthenticationToken authenticationToken=
                new UsernamePasswordAuthenticationToken(userDetails.getUsername(),
                        userDetails.getPassword(),userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        filterChain.doFilter(httpServletRequest,httpServletResponse);

    }
}
